package cn.edu.nju.ws.sview.wyge.servlets;

import java.io.IOException;
import java.net.URLDecoder;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.json.simple.JSONArray;
import org.json.simple.JSONObject;
import org.json.simple.JSONValue;

import cn.edu.nju.ws.sview.cache.URIIDCache;
import cn.edu.nju.ws.sview.wyge.relations.adataset.BasicTriplePattern.Mycomparator;
import cn.edu.nju.ws.sview.wyge.relations.adataset.CustomDataset;
import cn.edu.nju.ws.sview.wyge.relations.adataset.relations.Pattern;
import cn.edu.nju.ws.sview.wyge.relations.adataset.relations.Relation;
import cn.edu.nju.ws.sview.wyge.relations.adataset.relations.TriplePattern;
import cn.edu.nju.ws.sview.wyge.relations.adataset.relations.qxliu.relation.Expand;
import cn.edu.nju.ws.sview.wyge.relations.adataset.relations.qxliu.relation.ExpandFromTwoVariables;
import cn.edu.nju.ws.sview.wyge.relations.datasets.DatasetItem;

/**
 * 给定relation_id以及dataset得到relation的答案
 */
public class RelationExpand extends HttpServlet {
	private static final long serialVersionUID = 1L;

	/**
	 * @see HttpServlet#HttpServlet()
	 */
	public RelationExpand() {
		super();
		// TODO Auto-generated constructor stub
	}

	/**
	 * @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse
	 *      response)
	 */
	protected void doGet(HttpServletRequest request,
			HttpServletResponse response) throws ServletException, IOException {
		// TODO Auto-generated method stub
	}

	/**
	 * @see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse
	 *      response)
	 */
	@SuppressWarnings("unchecked")
	protected void doPost(HttpServletRequest request,
			HttpServletResponse response) throws ServletException, IOException {
		// TODO Auto-generated method stub
		String json = null;
		response.setCharacterEncoding("utf-8");
		if (request.getParameter("data") != null) {
			json = request.getParameter("data");
			String str = URLDecoder.decode(json, "UTF-8");
			System.out.println("in RelationExpand:"+str.toString());
			JSONObject regtJSON = (JSONObject) JSONValue.parse(str);
			int id = Integer.parseInt((String) regtJSON.get("id"));
			String ds_type = (String) regtJSON.get("ds_type");
			String idStr = (String) regtJSON.get("idStr");
			int ds_id = Integer.parseInt((String) regtJSON.get("ds_id"));
			String vars = (String) regtJSON.get("vars");

			ArrayList<Integer> docs = new ArrayList<Integer>();
			if (ds_type.equals(DatasetItem.URI_GENRE)) {
				docs.add(ds_id);
			} else if (ds_type.equals(DatasetItem.CUSTOM_GENRE)) {
				docs.addAll(CustomDataset.getURLIDsByCustomDatasetId(ds_id));
			}else if(ds_type.contentEquals(DatasetItem.TEMP_GENRE)){
				String[] strList = idStr.split("_");
				for(String did :strList){
					if(did.trim().length()>0){
						docs.add(Integer.parseInt(did));
					}
				}
			}
			Relation rel = (Relation) request.getSession().getAttribute(
					"relation" + id);

			Pattern pat = rel.getPattern();
			ArrayList<TriplePattern> triples = pat.getTriples();
			ArrayList<String[]> in = new ArrayList<String[]>();
			for (TriplePattern t : triples) {
				String[] row = new String[3];
				String s = t.getSubject();
				String p = "";
				String o = t.getObject();
				try {
					if (s.startsWith("u")) {
						int sid = Integer.parseInt(s.substring(1));
						s = "u" + URIIDCache.getInstance().getURI(sid);
					}
					p = "u" + URIIDCache.getInstance().getURI(t.getProperty());
					if (o.startsWith("u")) {
						int oid = Integer.parseInt(o.substring(1));
						o = "u" + URIIDCache.getInstance().getURI(oid);
					}
				} catch (Throwable e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
				row[0] = s;
				row[1] = p;
				row[2] = o;
				in.add(row);
			}

			ArrayList<ArrayList<String>> expands = null;
			String[] a = vars.split(",");
			System.out.println(a.toString()+"|"+a.length+"|"+(a.length == 2));
			if (a.length == 2) {//just used in old expand function, currently not used
//				expands = new ExpandFromTwoVariables().expand(in, docs, a[0], a[1]);
				expands = new ExpandFromTwoVariables(in, docs).expand(a[0], a[1]);
			} else {
				// for (String[] b : in) {
				// System.out.println(b[0] + " " + b[1] + " " + b[2]);
				// }
				// System.out.println(docs);
				// System.out.println(a[0]);
				expands = new Expand().expand(in, docs, a[0]);
			}

			Collections.sort(expands, new Mycomparator());

			JSONArray elements = new JSONArray();
			for (ArrayList<String> t : expands) {
				String s_code = t.get(0);
				String p_code = t.get(1);
				String o_code = t.get(2);
				// System.out.println(s_code + " " + p_code + " " + o_code);
				TriplePattern tp = TriplePattern.getTriple(s_code, p_code,
						o_code);
				JSONObject jsob = new JSONObject();
				jsob.put("stext", tp.getSubjectText());
				jsob.put("ptext", tp.getPropertyText());
				jsob.put("otext", tp.getObjectText());
				jsob.put("s", tp.getSubject());
				jsob.put("p", tp.getProperty());
				jsob.put("o", tp.getObject());
				elements.add(jsob);
			}

			JSONObject result = new JSONObject();
			result.put("result", elements);
			response.getWriter().print(result);
		}else if(request.getParameter("restrict") != null){
			json = request.getParameter("restrict");
			String str = URLDecoder.decode(json, "UTF-8");
			JSONObject regtJSON = (JSONObject) JSONValue.parse(str);
			int id = Integer.parseInt((String) regtJSON.get("id"));
			String ds_type = (String) regtJSON.get("ds_type");
			String idStr = (String) regtJSON.get("idStr");
			int ds_id = Integer.parseInt((String) regtJSON.get("ds_id"));
			String v = (String) regtJSON.get("v");

			ArrayList<Integer> docs = new ArrayList<Integer>();
			if (ds_type.equals(DatasetItem.URI_GENRE)) {
				docs.add(ds_id);
			} else if (ds_type.equals(DatasetItem.CUSTOM_GENRE)) {
				docs.addAll(CustomDataset.getURLIDsByCustomDatasetId(ds_id));
			}else if(ds_type.contentEquals(DatasetItem.TEMP_GENRE)){
				String[] strList = idStr.split("_");
				for(String did :strList){
					if(did.trim().length()>0){
						docs.add(Integer.parseInt(did));
					}
				}
			}

			Relation rel = (Relation) request.getSession().getAttribute(
					"relation" + id);

			Pattern pat = rel.getPattern();
			ArrayList<TriplePattern> triples = pat.getTriples();
			ArrayList<String[]> in = new ArrayList<String[]>();
			for (TriplePattern t : triples) {
				String[] row = new String[3];
				String s = t.getSubject();
				String p = "";
				String o = t.getObject();
				try {
					if (s.startsWith("u")) {
						int sid = Integer.parseInt(s.substring(1));
						s = "u" + URIIDCache.getInstance().getURI(sid);
					}
					p = "u" + URIIDCache.getInstance().getURI(t.getProperty());
					if (o.startsWith("u")) {
						int oid = Integer.parseInt(o.substring(1));
						o = "u" + URIIDCache.getInstance().getURI(oid);
					}
				} catch (Throwable e) {
					e.printStackTrace();
				}
				row[0] = s;
				row[1] = p;
				row[2] = o;
				in.add(row);
			}

			ArrayList<ArrayList<String>> expands = new ArrayList<ArrayList<String>>();
			ExpandFromTwoVariables eftv = new ExpandFromTwoVariables(in, docs);//ExpandFromTwoVariables();
			List<String> variables = rel.getVariables();
			for(String item : variables){
				if(!item.contentEquals(v)){
//					System.out.println("v:"+v+"|item:"+item);
//					expands.addAll(eftv.expand(in, docs, v, item));
//					expands.addAll(eftv.expand(in, docs, item, v));
					expands.addAll(eftv.expand(v, item));
					expands.addAll(eftv.expand(item, v));
				}
			}
			expands.addAll(eftv.expandOnType(v));
			
			Collections.sort(expands, new Mycomparator());

			JSONArray elements = new JSONArray();
			for (ArrayList<String> t : expands) {
				String s_code = t.get(0);
				String p_code = t.get(1);
				String o_code = t.get(2);
				TriplePattern tp = TriplePattern.getTriple(s_code, p_code,
						o_code);
				JSONObject jsob = new JSONObject();
				jsob.put("stext", tp.getSubjectText());
				jsob.put("ptext", tp.getPropertyText());
				jsob.put("otext", tp.getObjectText());
				jsob.put("s", tp.getSubject());
				jsob.put("p", tp.getProperty());
				jsob.put("o", tp.getObject());
				elements.add(jsob);
			}

			JSONObject result = new JSONObject();
			result.put("result", elements);
			response.getWriter().print(result);
		}
	}
}
